import { map } from 'lodash'
import { isNumber, isPlainObject, isString, values } from 'lodash-es'

import { QRCodeReq } from '@/api/sys/model/qrcode'
import { getWxMiniCode, getWxMiniCodeScene } from '@/api/sys/qrcode'
import { parseStrToObj } from '@/utils'

/**
 * 解析扫码进入的参数
 * @param strOrObj
 * @returns {Promise<Recordable>}
 */
export async function parseQrcode(
  strOrObj: string | Recordable
): Promise<Recordable> {
  if (!strOrObj) return {}

  let str: string
  if (isString(strOrObj)) {
    const tempUrl = decodeURIComponent(strOrObj)
    try {
      // 尝试解析为json
      const rs = JSON.parse(tempUrl)
      str =
        (isPlainObject(rs)
          ? rs.scene ?? rs
          : isNumber(rs)
          ? rs.toString()
          : rs) ?? ''
    } catch (e) {
      str = tempUrl.startsWith('scene=') ? tempUrl.substring(6) : tempUrl
    }
  } else {
    str = strOrObj.scene || ''
    str = decodeURIComponent(str)
    str = str.startsWith('scene=') ? str.substring(6) : str
  }

  if (isPlainObject(str)) return str as never

  // 新的参数格式
  if (/^\d_/.test(str)) {
    const [type, content] = str.split('_')

    // 原始数据类型
    if (+type === 1) {
      return parseStrToObj(content, ';', ',')
    } else if (+type === 2) {
      const rs = await getWxMiniCodeScene(content)
      return parseStrToObj(rs, ';', ',')
    }
    return {}
  } else {
    let id = ''
    // 兼容旧的参数格式
    if (/^\d+$/.test(str)) {
      id = str
    } else if (str.includes('id=')) {
      id = str.split('id=')[1]
    }

    if (id) {
      const rs = await getWxMiniCodeScene(id)
      return parseStrToObj(rs, ';', ',')
    }
    return parseStrToObj(str, ';', ',')
  }
}

/**
 * 生成小程序码,使用`useRequest`参数时，会自动调用生成小程序码接口，否则只返回格式化后的scene内容
 * @param scene
 * @param useRequest
 * @returns {Request<string>}
 */
export async function genMiniQrcode(
  scene: Recordable,
  useRequest: Omit<QRCodeReq, 'scene'>
): Promise<string> {
  const enableJsonStringify = values(scene).some((v) => !isString(v))

  const encodeStr = enableJsonStringify
    ? JSON.stringify(scene)
    : map(scene, (v, k) => `${k},${v}`).join(';')
  return getWxMiniCode({ ...useRequest, scene: encodeURIComponent(encodeStr) })
}
